package cn.tgq007.lock.controller;

import cn.tgq007.lock.http.GeneratorFeign;
import cn.tgq007.lock.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collections;

@RestController
@RequestMapping("/lock")
public class LockController {

    private final static String LOCK_KEY = "lock_key";

    private final static Long WAIT_TIME = 5 * 10000L;

    private final static String LOCK_LUA = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

    @Autowired
    private RedisService redisService;

    @Autowired
    private GeneratorFeign generatorFeign;

    private Integer serviceProcess() {
        // 从Redis中获取值
        Integer value = redisService.getCacheObject("tickets");
        // 将值减一
        value--;
        // 重新放回Redis中
        redisService.setCacheObject("tickets", value);
        return value;
    }

    @GetMapping("/noLock")
    public Integer unLockMethod() {
        return serviceProcess();
    }

    private Long unlock(String request) {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(LOCK_LUA, Long.class);
        return redisService.unlock(redisScript, Collections.singletonList(LOCK_KEY), request);
    }

    @GetMapping("/simpleRedisLock")
    public Integer simpleRedisLock() {
        Integer res = -100;
        String value = getGeneratorId();
        boolean redisLock = false;
        try {
            Long beforeTime = System.currentTimeMillis();
            while (true) {
                redisLock = redisService.tryLock(LOCK_KEY, value);
                if (redisLock) {
                    res = serviceProcess();
                    break;
                } else {
                    Long currentTime = System.currentTimeMillis();
                    if ((currentTime - beforeTime) >= WAIT_TIME) {
                        break;
                    }
                }
            }
        } finally {
            if (redisLock) {
                unlock(value);
            } else {
                System.out.println("获取锁失败！");
            }
        }
        return res;
    }

    private String getGeneratorId() {
        Long id = generatorFeign.generateId().getData();
        return String.valueOf(id);
    }
}
